﻿using LxBasic;

namespace LxCore
{
    public class UserMonitor : MonitorBase
    {
        public UserMonitor()
        {
            Name = "新建监测";
        }
        protected StatisticBase StatisticTool { get; set; }
        private StatisticTypes _StatisticTypes;
        public StatisticTypes StatisticType
        {
            get { return _StatisticTypes; }
            set
            {
                _StatisticTypes = value;
                switch (_StatisticTypes)
                {
                    case StatisticTypes.Min: StatisticTool = new ExtremeStatistic.Min(); break;
                    case StatisticTypes.Max: StatisticTool = new ExtremeStatistic.Max(); break;
                    case StatisticTypes.Mean: StatisticTool = new AverageStatistic.Mean(); break;
                    case StatisticTypes.Sum: StatisticTool = new IntegralStatistic.Sum(); break;
                    case StatisticTypes.VolumnAverage: StatisticTool = new AverageStatistic.VolumnAve(); break;
                    case StatisticTypes.VolumIntegral: StatisticTool = new IntegralStatistic.VolInt(); break;
                    case StatisticTypes.AreaAverage: StatisticTool = new AverageStatistic.AreaAve(); break;
                    case StatisticTypes.AreaIntegral: StatisticTool = new IntegralStatistic.AreaInt(); break;
                    case StatisticTypes.CostTime: StatisticTool = new CostTimeStatistic(); break;
                    default: LxLog.Error("功能未添加"); return;
                }
                RaisePropertyChanged(nameof(StatisticType));
            }
        }
        public ScalarFieldFinder ScalarFieldFinder { get; set; } = new ScalarFieldFinder(ScalarFieldTypes.Temperature);
        public ScalarFieldTypes ScalarType
        {
            get => ScalarFieldFinder.ScalarType;
            set
            {
                ScalarFieldFinder.ScalarType = value;
                RaisePropertyChanged(nameof(ScalarType));
            }
        }

        private MonitorTrigerTypes _MonitorTrigerType = MonitorTrigerTypes.Iteration;
        public MonitorTrigerTypes MonitorTrigerType
        {
            get { return _MonitorTrigerType; }
            set
            {
                if (_MonitorTrigerType != value)
                {
                    switch (value)
                    {
                        case MonitorTrigerTypes.Disable: HistoryData = null; break;
                        case MonitorTrigerTypes.Iteration:
                        case MonitorTrigerTypes.TimeStep:
                            HistoryData?.Clear();
                            break;
                    }
                    _MonitorTrigerType = value;
                }
                RaisePropertyChanged(nameof(MonitorTrigerType));
            }
        }
        public override void RunStatistic()
        {
            AccumulationDouble r = StatisticTool.RunReport(this);
            (IsLatestValueValid, LatestValue) = (!r.IsEmpty, r.Value);
        }
        public void SetSelector(FvBound zoneOrThread, bool isEnable = true)
        {
            ResHelper.GetCond(zoneOrThread).MonitorSelector[ID] = isEnable;
        }
        public void SetSelector(FvInner zoneOrThread, bool isEnable = true)
        {
            ResHelper.GetCond(zoneOrThread.InZone).InnerCond.MonitorSelector[ID] = isEnable;
        }
        public IEnumerable<(FvInner Inner, FvZone Zone, ZoneCond ZoneCond, ICellVarArr<double>? CellVars)> GetSelectedZone()
        {
            foreach (var zc in LxSim.Sim.Conditions.ZoneConds)
            {
                if (zc.InnerCond.MonitorSelector[ID])
                {
                    yield return (zc.Zone.Inner, zc.Zone, zc, ScalarFieldFinder.GetCellVarArr(zc.Zone.Inner));
                }
            }
        }
        public IEnumerable<(FvBound Bound, FvZone Zone, BoundCond BoundCond, IFaceVarArr<double>? FaceVars)> GetSelectedBound(ZoneCond zoneCond)
        {
            foreach (var bc in zoneCond.BoundConds)
            {
                if (bc.MonitorSelector[ID])
                {
                    yield return (bc.Bound, bc.Bound.InZone, bc, ScalarFieldFinder.GetFaceVarArr(bc.Bound));
                }
            }
        }
        public override void FromJsonKV(string key, IJsonReader jsReader)
        {
            switch (key)
            {
                case nameof(StatisticType): StatisticType = jsReader.ReadEnum<StatisticTypes>(); break;
                case nameof(ScalarType): ScalarType = jsReader.ReadEnum<ScalarFieldTypes>(); break;
                case nameof(MonitorTrigerType): MonitorTrigerType = jsReader.ReadEnum<MonitorTrigerTypes>(); break;
                case "Selector":jsReader.ReadMonitorSelector(this); break;
                default: base.FromJsonKV(key, jsReader); break;
            }
        }
        public override void ToJsonKV(IJsonWriter jsWriter)
        {
            base.ToJsonKV(jsWriter);
            jsWriter.WriteEnum(nameof(StatisticType), StatisticType);
            jsWriter.WriteEnum(nameof(ScalarType), ScalarType);
            jsWriter.WriteEnum(nameof(MonitorTrigerType), MonitorTrigerType);
            jsWriter.WriteMonitorSelector("Selector", this.ID);
        }

    }
}